/*
                 __________                                      
    _____   __ __\______   \_____  _______  ______  ____ _______ 
   /     \ |  |  \|     ___/\__  \ \_  __ \/  ___/_/ __ \\_  __ \
  |  Y Y  \|  |  /|    |     / __ \_|  | \/\___ \ \  ___/ |  | \/
  |__|_|  /|____/ |____|    (____  /|__|  /____  > \___  >|__|   
        \/                       \/            \/      \/        
  Copyright (C) 2004-2011 Ingo Berg

  Permission is hereby granted, free of charge, to any person obtaining a copy of this 
  software and associated documentation files (the "Software"), to deal in the Software
  without restriction, including without limitation the rights to use, copy, modify, 
  merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 
  permit persons to whom the Software is furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in all copies or 
  substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
  NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
*/
#if defined(MUMathParser_DLL) 

#if defined(_WIN32)
  #define WIN32_LEAN_AND_MEAN
  #include <windows.h>
#endif

#include "muParserDLL.h"
#include "muParser.h"
#include "muParserInt.h"
#include "muParserError.h"


#define MU_TRY  \
        try     \
        {

#define MU_CATCH                                                 \
        }                                                        \
        catch(muError_t &e)                                      \
        {                                                        \
          MathParserTag *pTag = static_cast<MathParserTag*>(a_hMathParser);  \
          pTag->exc = e;                                         \
          pTag->bError = true;                                   \
          if (pTag->errHandler)                                  \
            (pTag->errHandler)(a_hMathParser);                       \
        }                                                        \
        catch(...)                                               \
        {                                                        \
          MathParserTag *pTag = static_cast<MathParserTag*>(a_hMathParser);  \
          pTag->exc = muError_t(mu::ecINTERNAL_ERROR);           \
          pTag->bError = true;                                   \
          if (pTag->errHandler)                                  \
            (pTag->errHandler)(a_hMathParser);                       \
        }

/** \file 
    \brief This file contains the implementation of the DLL interface of muMathParser.
*/

//---------------------------------------------------------------------------
// private types
typedef mu::MathParserBase::exception_type muError_t;
typedef mu::MathParserBase muMathParser_t;

int g_nBulkSize;

//---------------------------------------------------------------------------
class MathParserTag
{
public:
  MathParserTag(int nType)
    :pMathParser( (nType==muBASETYPE_FLOAT)   ? (mu::MathParserBase*)new mu::MathParser()    : 
              (nType==muBASETYPE_INT)     ? (mu::MathParserBase*)new mu::MathParserInt() : NULL)
    ,exc()
    ,errHandler(NULL)
    ,bError(false)
    ,m_nMathParserType(nType)
  {}
 
 ~MathParserTag()
  {
    delete pMathParser;
  }

  mu::MathParserBase *pMathParser;
  mu::MathParserBase::exception_type exc;
  muErrorHandler_t errHandler;
  bool bError;

private:
  MathParserTag(const MathParserTag &ref);
  MathParserTag& operator=(const MathParserTag &ref);

  int m_nMathParserType;
};

static muChar_t s_tmpOutBuf[2048];

//---------------------------------------------------------------------------
//
//
//  unexported functions
//
//
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
muMathParser_t* AsMathParser(muMathParserHandle_t a_hMathParser)
{
  return static_cast<MathParserTag*>(a_hMathParser)->pMathParser;
}

//---------------------------------------------------------------------------
MathParserTag* AsMathParserTag(muMathParserHandle_t a_hMathParser)
{
  return static_cast<MathParserTag*>(a_hMathParser);
}

//---------------------------------------------------------------------------
#if defined(_WIN32)
  #define _CRT_SECURE_NO_DEPRECATE

  BOOL APIENTRY DllMain( HANDLE /*hModule*/, 
                         DWORD ul_reason_for_call, 
                         LPVOID /*lpReserved*/ )
  {
	  switch (ul_reason_for_call)
	  {
	  case  DLL_PROCESS_ATTACH:
          break;

    case  DLL_THREAD_ATTACH:
    case  DLL_THREAD_DETACH:
    case  DLL_PROCESS_DETACH:
    		  break;
	  }

    return TRUE;
  }

#endif

//---------------------------------------------------------------------------
//
//
//  exported functions
//
//
//---------------------------------------------------------------------------

API_EXPORT(void) mupSetVarFactory(muMathParserHandle_t a_hMathParser, muFacFun_t a_pFactory, void *pUserData)
{
  MU_TRY
    muMathParser_t* p(AsMathParser(a_hMathParser));
    p->SetVarFactory(a_pFactory, pUserData);
  MU_CATCH
}

//---------------------------------------------------------------------------
/** \brief Create a new MathParser instance and return its handle.
*/
API_EXPORT(muMathParserHandle_t) mupCreate(int nBaseType)
{
  switch(nBaseType)
  {
  case  muBASETYPE_FLOAT:   return (void*)(new MathParserTag(muBASETYPE_FLOAT));
  case  muBASETYPE_INT:     return (void*)(new MathParserTag(muBASETYPE_INT));
  default:                  return NULL;
  }
}

//---------------------------------------------------------------------------
/** \brief Release the MathParser instance related with a MathParser handle.
*/
API_EXPORT(void) mupRelease(muMathParserHandle_t a_hMathParser)
{
  MU_TRY
    MathParserTag* p = static_cast<MathParserTag*>(a_hMathParser);
    delete p;
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(const muChar_t*) mupGetVersion(muMathParserHandle_t a_hMathParser)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    sprintf(s_tmpOutBuf, "%s", p->GetVersion().c_str());
    return s_tmpOutBuf;
  MU_CATCH

  return "";
}

//---------------------------------------------------------------------------
/** \brief Evaluate the expression.
*/
API_EXPORT(muFloat_t) mupEval(muMathParserHandle_t a_hMathParser)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    return p->Eval();
  MU_CATCH

  return 0;
}

//---------------------------------------------------------------------------
API_EXPORT(muFloat_t*) mupEvalMulti(muMathParserHandle_t a_hMathParser, int *nNum)
{
  MU_TRY
    assert(nNum!=NULL);

    muMathParser_t* const p(AsMathParser(a_hMathParser));
    return p->Eval(*nNum);
  MU_CATCH

  return 0;
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupEvalBulk(muMathParserHandle_t a_hMathParser, muFloat_t *a_res, int nSize)
{
  MU_TRY
    muMathParser_t* p(AsMathParser(a_hMathParser));
    p->Eval(a_res, nSize);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupSetExpr(muMathParserHandle_t a_hMathParser, const muChar_t* a_szExpr)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->SetExpr(a_szExpr);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupRemoveVar(muMathParserHandle_t a_hMathParser, const muChar_t* a_szName)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->RemoveVar( a_szName );
  MU_CATCH
}

//---------------------------------------------------------------------------
/** \brief Release all MathParser variables.
    \param a_hMathParser Handle to the MathParser instance.
*/
API_EXPORT(void) mupClearVar(muMathParserHandle_t a_hMathParser)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->ClearVar();
  MU_CATCH
}

//---------------------------------------------------------------------------
/** \brief Release all MathParser variables.
    \param a_hMathParser Handle to the MathParser instance.
*/
API_EXPORT(void) mupClearConst(muMathParserHandle_t a_hMathParser)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->ClearConst();
  MU_CATCH
}

//---------------------------------------------------------------------------
/** \brief Clear all user defined operators.
    \param a_hMathParser Handle to the MathParser instance.
*/
API_EXPORT(void) mupClearOprt(muMathParserHandle_t a_hMathParser)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->ClearOprt();
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupClearFun(muMathParserHandle_t a_hMathParser)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->ClearFun();
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun0( muMathParserHandle_t a_hMathParser, 
                                const muChar_t* a_szName, 
                                muFun0_t a_pFun, 
                                muBool_t a_bAllowOpt )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun1( muMathParserHandle_t a_hMathParser, 
                                const muChar_t* a_szName, 
                                muFun1_t a_pFun, 
                                muBool_t a_bAllowOpt )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun2( muMathParserHandle_t a_hMathParser, 
                                const muChar_t* a_szName, 
                                muFun2_t a_pFun, 
                                muBool_t a_bAllowOpt )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun3( muMathParserHandle_t a_hMathParser, 
                                const muChar_t *a_szName, 
                                muFun3_t a_pFun, 
                                muBool_t a_bAllowOpt )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun4( muMathParserHandle_t a_hMathParser, 
                                const muChar_t *a_szName, 
                                muFun4_t a_pFun, 
                                muBool_t a_bAllowOpt )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun5( muMathParserHandle_t a_hMathParser, 
                                const muChar_t *a_szName, 
                                muFun5_t a_pFun, 
                                muBool_t a_bAllowOpt )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun6( muMathParserHandle_t a_hMathParser, 
                                const muChar_t *a_szName, 
                                muFun6_t a_pFun, 
                                muBool_t a_bAllowOpt )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun7( muMathParserHandle_t a_hMathParser, 
                                const muChar_t *a_szName, 
                                muFun7_t a_pFun, 
                                muBool_t a_bAllowOpt )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun8( muMathParserHandle_t a_hMathParser, 
                                const muChar_t *a_szName, 
                                muFun8_t a_pFun, 
                                muBool_t a_bAllowOpt )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun9( muMathParserHandle_t a_hMathParser, 
                                const muChar_t *a_szName, 
                                muFun9_t a_pFun, 
                                muBool_t a_bAllowOpt )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineFun10( muMathParserHandle_t a_hMathParser, 
                                const muChar_t *a_szName, 
                                muFun10_t a_pFun, 
                                muBool_t a_bAllowOpt )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineBulkFun0(muMathParserHandle_t a_hMathParser, 
                                   const muChar_t* a_szName, 
                                   muBulkFun0_t a_pFun)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, false);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineBulkFun1(muMathParserHandle_t a_hMathParser, 
                                   const muChar_t* a_szName, 
                                   muBulkFun1_t a_pFun)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, false);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineBulkFun2(muMathParserHandle_t a_hMathParser, 
                                   const muChar_t* a_szName, 
                                   muBulkFun2_t a_pFun)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, false);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineBulkFun3(muMathParserHandle_t a_hMathParser, 
                                   const muChar_t *a_szName, 
                                   muBulkFun3_t a_pFun)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, false);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineBulkFun4(muMathParserHandle_t a_hMathParser, 
                                   const muChar_t *a_szName, 
                                   muBulkFun4_t a_pFun)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, false);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineBulkFun5(muMathParserHandle_t a_hMathParser, 
                                   const muChar_t *a_szName, 
                                   muBulkFun5_t a_pFun)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, false);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineBulkFun6(muMathParserHandle_t a_hMathParser, 
                                   const muChar_t *a_szName, 
                                   muBulkFun6_t a_pFun)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, false);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineBulkFun7(muMathParserHandle_t a_hMathParser, 
                                   const muChar_t *a_szName, 
                                   muBulkFun7_t a_pFun)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, false);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineBulkFun8(muMathParserHandle_t a_hMathParser, 
                                   const muChar_t *a_szName, 
                                   muBulkFun8_t a_pFun)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, false);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineBulkFun9(muMathParserHandle_t a_hMathParser, 
                                   const muChar_t *a_szName, 
                                   muBulkFun9_t a_pFun)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, false);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineBulkFun10( muMathParserHandle_t a_hMathParser, 
                                     const muChar_t *a_szName, 
                                     muBulkFun10_t a_pFun)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, false);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineStrFun1( muMathParserHandle_t a_hMathParser, 
                                   const muChar_t *a_szName, 
                                   muStrFun1_t a_pFun )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, false);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineStrFun2( muMathParserHandle_t a_hMathParser, 
                                   const muChar_t* a_szName, 
                                   muStrFun2_t a_pFun )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, false);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineStrFun3( muMathParserHandle_t a_hMathParser, 
                                   const muChar_t* a_szName, 
                                   muStrFun3_t a_pFun )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, false);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineMultFun( muMathParserHandle_t a_hMathParser, 
                                   const muChar_t *a_szName, 
                                   muMultFun_t a_pFun, 
                                   muBool_t a_bAllowOpt )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineFun(a_szName, a_pFun, a_bAllowOpt!=0);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineOprt( muMathParserHandle_t a_hMathParser, 
                                const muChar_t* a_szName, 
                                muFun2_t a_pFun, 
                                muInt_t a_nPrec, 
                                muInt_t a_nOprtAsct,
                                muBool_t a_bAllowOpt)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineOprt(a_szName, 
                  a_pFun, 
                  a_nPrec, 
                  (mu::EOprtAssociativity)a_nOprtAsct, 
                  a_bAllowOpt!=0);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineVar(muMathParserHandle_t a_hMathParser, 
                              const muChar_t *a_szName, 
                              muFloat_t *a_pVar)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineVar(a_szName, a_pVar);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineBulkVar(muMathParserHandle_t a_hMathParser, 
                                  const muChar_t *a_szName, 
                                  muFloat_t *a_pVar)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineVar(a_szName, a_pVar);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineConst(muMathParserHandle_t a_hMathParser, 
								const muChar_t *a_szName, 
								muFloat_t a_fVal)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineConst(a_szName, a_fVal);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineStrConst(muMathParserHandle_t a_hMathParser, 
								   const muChar_t *a_szName, 
								   const muChar_t *a_szVal)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineStrConst(a_szName, a_szVal);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(const muChar_t*) mupGetExpr(muMathParserHandle_t a_hMathParser)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));

    // C# explodes when pMsg is returned directly. For some reason it can't access
    // the memory where the message lies directly.
    sprintf(s_tmpOutBuf, "%s", p->GetExpr().c_str());
    return s_tmpOutBuf;
  
  MU_CATCH

  return "";
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefinePostfixOprt( muMathParserHandle_t a_hMathParser,
                                       const muChar_t* a_szName,
                                       muFun1_t a_pOprt,
                                       muBool_t a_bAllowOpt )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefinePostfixOprt(a_szName, a_pOprt, a_bAllowOpt!=0);
  MU_CATCH
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineInfixOprt( muMathParserHandle_t a_hMathParser,
                                     const muChar_t* a_szName,
                                     muFun1_t a_pOprt,
                                     muBool_t a_bAllowOpt )
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->DefineInfixOprt(a_szName, a_pOprt, a_bAllowOpt!=0);
  MU_CATCH
}

// Define character sets for identifiers
//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineNameChars( muMathParserHandle_t a_hMathParser, 
                                     const muChar_t* a_szCharset )
{
    muMathParser_t* const p(AsMathParser(a_hMathParser));
  p->DefineNameChars(a_szCharset);
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineOprtChars( muMathParserHandle_t a_hMathParser, 
                                     const muChar_t* a_szCharset )
{
  muMathParser_t* const p(AsMathParser(a_hMathParser));
  p->DefineOprtChars(a_szCharset);
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupDefineInfixOprtChars(muMathParserHandle_t a_hMathParser, 
										 const muChar_t *a_szCharset)
{
  muMathParser_t* const p(AsMathParser(a_hMathParser));
  p->DefineInfixOprtChars(a_szCharset);
}

//---------------------------------------------------------------------------
/** \brief Get the number of variables defined in the MathParser.
    \param a_hMathParser [in] Must be a valid MathParser handle.
    \return The number of used variables.
    \sa mupGetExprVar
*/
API_EXPORT(int) mupGetVarNum(muMathParserHandle_t a_hMathParser)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    const mu::varmap_type VarMap = p->GetVar();
    return (int)VarMap.size();
  MU_CATCH

  return 0; // never reached
}

//---------------------------------------------------------------------------
/** \brief Return a variable that is used in an expression.
    \param a_hMathParser [in] A valid MathParser handle.
    \param a_iVar [in] The index of the variable to return.
    \param a_szName [out] Pointer to the variable name.
    \param a_pVar [out] Pointer to the variable.
    \throw nothrow

    Prior to calling this function call mupGetExprVarNum in order to get the
    number of variables in the expression. If the parameter a_iVar is greater
    than the number of variables both a_szName and a_pVar will be set to zero.
    As a side effect this function will trigger an internal calculation of the
    expression undefined variables will be set to zero during this calculation.
    During the calculation user defined callback functions present in the expression
    will be called, this is unavoidable.
*/
API_EXPORT(void) mupGetVar(muMathParserHandle_t a_hMathParser, 
						   unsigned a_iVar, 
						   const muChar_t **a_szName, 
						   muFloat_t **a_pVar)
{
  // A static buffer is needed for the name since i cant return the
  // pointer from the map.
  static muChar_t  szName[1024];

  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    const mu::varmap_type VarMap = p->GetVar();

    if (a_iVar>=VarMap.size())
    {
     *a_szName = 0;
     *a_pVar = 0;
      return;
    }
    mu::varmap_type::const_iterator item;

    item = VarMap.begin();
    for (unsigned i=0; i<a_iVar; ++i)
      item++;

     strncpy(szName, item->first.c_str(), sizeof(szName));
     szName[sizeof(szName)-1] = 0;

    *a_szName = &szName[0];
    *a_pVar = item->second;
     return;

  MU_CATCH

  *a_szName = 0;
  *a_pVar = 0;
}

//---------------------------------------------------------------------------
/** \brief Get the number of variables used in the expression currently set in the MathParser.
    \param a_hMathParser [in] Must be a valid MathParser handle.
    \return The number of used variables.
    \sa mupGetExprVar
*/
API_EXPORT(int) mupGetExprVarNum(muMathParserHandle_t a_hMathParser)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    const mu::varmap_type VarMap = p->GetUsedVar();
    return (int)VarMap.size();
  MU_CATCH

  return 0; // never reached
}

//---------------------------------------------------------------------------
/** \brief Return a variable that is used in an expression.

    Prior to calling this function call mupGetExprVarNum in order to get the
    number of variables in the expression. If the parameter a_iVar is greater
    than the number of variables both a_szName and a_pVar will be set to zero.
    As a side effect this function will trigger an internal calculation of the
    expression undefined variables will be set to zero during this calculation.
    During the calculation user defined callback functions present in the expression
    will be called, this is unavoidable.

    \param a_hMathParser [in] A valid MathParser handle.
    \param a_iVar [in] The index of the variable to return.
    \param a_szName [out] Pointer to the variable name.
    \param a_pVar [out] Pointer to the variable.
    \throw nothrow
*/
API_EXPORT(void) mupGetExprVar(muMathParserHandle_t a_hMathParser, 
							   unsigned a_iVar, 
							   const muChar_t **a_szName, 
							   muFloat_t **a_pVar)
{
  // A static buffer is needed for the name since i cant return the
  // pointer from the map.
  static muChar_t  szName[1024];

  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    const mu::varmap_type VarMap = p->GetUsedVar();

    if (a_iVar>=VarMap.size())
    {
     *a_szName = 0;
     *a_pVar = 0;
      return;
    }
    mu::varmap_type::const_iterator item;

    item = VarMap.begin();
    for (unsigned i=0; i<a_iVar; ++i)
      item++;

     strncpy(szName, item->first.c_str(), sizeof(szName));
     szName[sizeof(szName)-1] = 0;

    *a_szName = &szName[0];
    *a_pVar = item->second;
     return;

  MU_CATCH

  *a_szName = 0;
  *a_pVar = 0;
}

//---------------------------------------------------------------------------
/** \brief Return the number of constants defined in a MathParser. */
API_EXPORT(int) mupGetConstNum(muMathParserHandle_t a_hMathParser)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    const mu::valmap_type ValMap = p->GetConst();
    return (int)ValMap.size();
  MU_CATCH

  return 0; // never reached
}

//-----------------------------------------------------------------------------------------------------
API_EXPORT(void) mupSetArgSep(muMathParserHandle_t a_hMathParser, const muChar_t cArgSep)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->SetArgSep(cArgSep);
  MU_CATCH
}

//-----------------------------------------------------------------------------------------------------
API_EXPORT(void) mupResetLocale(muMathParserHandle_t a_hMathParser)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->ResetLocale();
  MU_CATCH
}

//-----------------------------------------------------------------------------------------------------
API_EXPORT(void) mupSetDecSep(muMathParserHandle_t a_hMathParser, const muChar_t cDecSep)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->SetDecSep(cDecSep);
  MU_CATCH
}

//-----------------------------------------------------------------------------------------------------
API_EXPORT(void) mupSetThousandsSep(muMathParserHandle_t a_hMathParser, const muChar_t cThousandsSep)
{
  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    p->SetThousandsSep(cThousandsSep);
  MU_CATCH
}

//---------------------------------------------------------------------------
/** \brief Retrieve name and value of a single MathParser constant.
    \param a_hMathParser [in] a valid MathParser handle
    \param a_iVar [in] Index of the constant to query
    \param a_pszName [out] pointer to a null terminated string with the constant name
    \param [out] The constant value
*/
API_EXPORT(void) mupGetConst( muMathParserHandle_t a_hMathParser, 
                              unsigned a_iVar,
                              const muChar_t **a_pszName, 
                              muFloat_t *a_fVal)
{
  // A static buffer is needed for the name since i cant return the
  // pointer from the map.
  static muChar_t szName[1024];

  MU_TRY
    muMathParser_t* const p(AsMathParser(a_hMathParser));
    const mu::valmap_type ValMap = p->GetConst();

    if (a_iVar>=ValMap.size())
    {
     *a_pszName = 0;
     *a_fVal = 0;
      return;
    }

    mu::valmap_type::const_iterator item;
    item = ValMap.begin();
    for (unsigned i=0; i<a_iVar; ++i)
      item++;

    strncpy(szName, item->first.c_str(), sizeof(szName));
    szName[sizeof(szName)-1] = 0;

    *a_pszName = &szName[0];
    *a_fVal = item->second;
     return;

  MU_CATCH

  *a_pszName = 0;
  *a_fVal = 0;
}

//---------------------------------------------------------------------------
/** \brief Add a custom value regognition function.
*/
API_EXPORT(void) mupAddValIdent(muMathParserHandle_t a_hMathParser, 
                                muIdentFun_t a_pFun)
{
  MU_TRY
    muMathParser_t* p(AsMathParser(a_hMathParser));
    p->AddValIdent(a_pFun);
  MU_CATCH
}

//---------------------------------------------------------------------------
/** \brief Query if an error occured.

    After querying the internal error bit will be reset. So a consecutive call
    will return false.
*/
API_EXPORT(muBool_t) mupError(muMathParserHandle_t a_hMathParser)
{
  bool bError( AsMathParserTag(a_hMathParser)->bError );
  AsMathParserTag(a_hMathParser)->bError = false;
  return bError;
}

//---------------------------------------------------------------------------
/** \brief Reset the internal error flag.
*/
API_EXPORT(void) mupErrorReset(muMathParserHandle_t a_hMathParser)
{
  AsMathParserTag(a_hMathParser)->bError = false;
}

//---------------------------------------------------------------------------
API_EXPORT(void) mupSetErrorHandler(muMathParserHandle_t a_hMathParser, muErrorHandler_t a_pHandler)
{
  AsMathParserTag(a_hMathParser)->errHandler = a_pHandler;
}

//---------------------------------------------------------------------------
/** \brief Return the message associated with the last error.
*/
API_EXPORT(const muChar_t*) mupGetErrorMsg(muMathParserHandle_t a_hMathParser)
{
  MathParserTag* const p(AsMathParserTag(a_hMathParser));
  const muChar_t *pMsg = p->exc.GetMsg().c_str();

  // C# explodes when pMsg is returned directly. For some reason it can't access
  // the memory where the message lies directly.
  sprintf(s_tmpOutBuf, "%s", pMsg);
  return s_tmpOutBuf;
}

//---------------------------------------------------------------------------
/** \brief Return the message associated with the last error.
*/
API_EXPORT(const muChar_t*) mupGetErrorToken(muMathParserHandle_t a_hMathParser)
{
  MathParserTag* const p(AsMathParserTag(a_hMathParser));
  const muChar_t *pToken = p->exc.GetToken().c_str();

  // C# explodes when pMsg is returned directly. For some reason it can't access
  // the memory where the message lies directly.
  sprintf(s_tmpOutBuf, "%s", pToken);
  return s_tmpOutBuf;
}

//---------------------------------------------------------------------------
/** \brief Return the code associated with the last error.
*/
API_EXPORT(int) mupGetErrorCode(muMathParserHandle_t a_hMathParser)
{
  return AsMathParserTag(a_hMathParser)->exc.GetCode();
}

//---------------------------------------------------------------------------
/** \brief Return the postion associated with the last error. */
API_EXPORT(int) mupGetErrorPos(muMathParserHandle_t a_hMathParser)
{
  return (int)AsMathParserTag(a_hMathParser)->exc.GetPos();
}

////-----------------------------------------------------------------------------------------------------
//API_EXPORT(const muChar_t*) mupGetErrorExpr(muMathParserHandle_t a_hMathParser)
//{
//  return AsMathParserTag(a_hMathParser)->exc.GetExpr().c_str();
//}

//-----------------------------------------------------------------------------------------------------
API_EXPORT(muFloat_t*) mupCreateVar()
{
  return new muFloat_t(0);
}

//-----------------------------------------------------------------------------------------------------
API_EXPORT(void) mupReleaseVar(muFloat_t *ptr)
{
  delete ptr;
}

#endif      // MUMathParser_DLL
